package com.xxxtea.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxxtea.common.Result;
import com.xxxtea.common.UserContext;
import com.xxxtea.common.execption.BusinessException;
import com.xxxtea.dto.Location;
import com.xxxtea.dto.PageQuery;
import com.xxxtea.dto.TaskAbnormalRequest;
import com.xxxtea.entity.Review;
import com.xxxtea.entity.Task;
import com.xxxtea.entity.TaskStage;
import com.xxxtea.entity.TaskStage.IsAbnormal;
import com.xxxtea.entity.TaskStage.Status;
import com.xxxtea.entity.User;
import com.xxxtea.sdk.amap.AmapClient;
import com.xxxtea.sdk.amap.AmapResult;
import com.xxxtea.service.ReviewService;
import com.xxxtea.service.TaskService;
import com.xxxtea.service.TaskStageService;
import com.xxxtea.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

/**
 * 跑腿任务控制器
 *
 * 提供跑腿任务的完整管理功能，包括：
 * - 任务的增删改查
 * - 任务接单和异常处理
 * - 地理位置处理和距离计算
 * - 分页查询和条件筛选
 * - 任务阶段管理
 *
 * 使用Swagger注解进行API文档生成
 * 使用Lombok注解简化代码
 *
 * @author badman
 * @since 1.0.0
 */
@Slf4j
@Api("跑腿任务接口")
@RestController
@RequestMapping("/task")
public class TaskController {
	/**
	 * 高德地图客户端
	 */
	@Resource
	private AmapClient amapClient;
	
	/**
	 * 任务服务
	 */
	@Resource
	private TaskService taskService;
	
	/**
	 * 任务阶段服务
	 */
	@Resource
	private TaskStageService taskStageService;
	
	/**
	 * 评价服务
	 */
	@Resource
	private ReviewService reviewService;
	
	/**
	 * 用户服务
	 */
	@Resource
	private UserService userService;

	/**
	 * 上报任务异常
	 *
	 * @param request 异常请求信息
	 * @return 操作结果
	 */
	@PostMapping("/abnormal")
	@Operation(summary = "上报异常")
	public Result<String> abnormal(@RequestBody TaskAbnormalRequest request) {
		Task task = taskService.getById(request.getTaskId());
		task.setIsAbnormal(Task.IsAbnormal.YES);
		task.setAbnormalReason(request.getReason());
		taskService.updateById(task);
		return Result.success();
	}

	/**
	 * 接单
	 * 用户接取任务，更新任务状态并创建任务阶段
	 *
	 * @param id 任务ID
	 * @return 操作结果
	 */
	@PostMapping("/pick/{id}")
	@Operation(summary = "接单人用户信息")
	public Result<String> pick(@PathVariable Integer id) {
		Task task = taskService.getById(id);
		task.setAcceptorId(UserContext.getId());
		task.setStatus(Task.Status.PROGRESS);
		taskService.updateById(task);

		// 创建任务阶段记录
		TaskStage taskStage = new TaskStage();
		taskStage.setTaskId(id);
		taskStage.setStatus(Status.Type1);
		taskStage.setIsAbnormal(IsAbnormal.NO);
		taskStageService.save(taskStage);
		return Result.success();
	}

	/**
	 * 新增跑腿任务
	 * 自动获取地址的经纬度信息
	 *
	 * @param request 任务信息
	 * @return 操作结果
	 */
	@PostMapping
	@ApiOperation("新增跑腿任务")
	public Result<String> save(@RequestBody Task request) {
		try {
			// 通过高德地图API获取精确经纬度
			if (StrUtil.isBlank(request.getOriginAddress())) {
				AmapResult.Geocode originLocation = CollUtil.getFirst(amapClient.getLocation(request.getOriginAddress()));
				request.setOriginLocation(Location.of(originLocation.getLocation()));
			}
			if (StrUtil.isBlank(request.getDestAddress())) {
				AmapResult.Geocode destLocation = CollUtil.getFirst(amapClient.getLocation(request.getDestAddress()));
				request.setDestLocation(Location.of(destLocation.getLocation()));
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BusinessException("任务地点和任务目的地有误");
		}
		if (!taskService.save(request)) {
			return Result.error("添加失败!");
		}
		return Result.success();
	}

	/**
	 * 删除跑腿任务
	 *
	 * @param id 任务ID
	 * @return 操作结果
	 */
	@DeleteMapping("/{id}")
	@ApiOperation("删除跑腿任务")
	public Result<String> removeById(@PathVariable String id) {
		if (!taskService.removeById(id)) {
			return Result.error("删除失败!");
		}
		return Result.success();
	}

	/**
	 * 更新跑腿任务
	 *
	 * @param request 任务信息
	 * @return 操作结果
	 */
	@PutMapping
	@ApiOperation("更新跑腿任务")
	public Result<String> updateById(@RequestBody Task request) {
		if (!taskService.updateById(request)) {
			return Result.error("更新失败!");
		}
		return Result.success();
	}

	/**
	 * 查询跑腿任务详情
	 * 包含发布者信息、评价列表和任务阶段
	 *
	 * @param id 任务ID
	 * @return 任务详情信息
	 */
	@GetMapping("/{id}")
	@ApiOperation("查询跑腿任务详情")
	public Result<Task> getById(@PathVariable String id) {
		Task task = taskService.getById(id);
		// 获取发布者信息
		User user = userService.getById(task.getPublisherId());
		// 查询发布者的评价列表
		List<Review> reviewList = reviewService.lambdaQuery().eq(Review::getBusinessType, Review.BusinessType.TASK)
				.eq(Review::getBusinessId, task.getPublisherId())
				.list();
		task.setPublisher(user);
		task.setReviewList(reviewList);
		// 设置任务阶段信息
		taskService.setTaskStages(Collections.singletonList(task));
		return Result.success(task);
	}

	/**
	 * 查询跑腿任务列表
	 *
	 * @param request 查询条件
	 * @return 任务列表
	 */
	@GetMapping("/list")
	@ApiOperation("查询跑腿任务列表")
	public Result<List<Task>> list(Task request) {
		LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>(request);
		return Result.success(taskService.list(wrapper));
	}

	/**
	 * 分页查询跑腿任务
	 * 支持状态、接单者、发布者、报酬范围、距离范围等条件筛选
	 *
	 * @param request 分页查询条件
	 * @return 分页任务列表
	 */
	@PostMapping("/page")
	@ApiOperation("分页查询跑腿任务")
	public Result<Page<Task>> page(@RequestBody PageQuery<Task> request) {
		Task param = request.getParam();
		LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>(param);
		// 按ID倒序排列
		wrapper.orderByDesc(Task::getId);
		// 状态列表筛选
		wrapper.in(CollUtil.isNotEmpty(param.getStatusList()), Task::getStatus, param.getStatusList());

		// 接单者筛选（我接单的/非我接单的）
		Boolean acceptedByMe = param.getAcceptedByMe();
		if (acceptedByMe != null) {
			wrapper.eq(acceptedByMe, Task::getAcceptorId, UserContext.getId());
			wrapper.ne(!acceptedByMe, Task::getAcceptorId, UserContext.getId());
		}

		// 发布者筛选（我发布的/非我发布的）
		Boolean publishedByMe = param.getPublishedByMe();
		if (publishedByMe != null) {
			wrapper.eq(publishedByMe, Task::getPublisherId, UserContext.getId());
			wrapper.ne(!publishedByMe, Task::getPublisherId, UserContext.getId());
		}

		// 报酬范围筛选
		wrapper.ge(param.getMinReward() != null, Task::getReward, param.getMinReward());
		wrapper.le(param.getMaxReward() != null, Task::getReward, param.getMaxReward());
		// 距离范围筛选
		wrapper.ge(param.getMinDistance() != null, Task::getDistance, param.getMinDistance());
		wrapper.le(param.getMaxDistance() != null, Task::getDistance, param.getMaxDistance());

		Page<Task> pageResult = taskService.page(request.toPage(), wrapper);
		// 计算距离和设置用户关系标识
		for (Task record : pageResult.getRecords()) {
			Location originLocation = record.getOriginLocation();
			Location userLocation = UserContext.getUser().getLocation();
			record.setStartDistance(amapClient.distanceKm(originLocation, userLocation));
			record.setPublishedByMe(UserContext.getId().equals(record.getPublisherId()));
			record.setAcceptedByMe(UserContext.getId().equals(record.getAcceptorId()));
		}
		// 设置任务阶段信息
		taskService.setTaskStages(pageResult.getRecords());
		return Result.success(pageResult);
	}
}